<script>
import {
  defineComponent,
  reactive,
  watch,
  nextTick,
  getCurrentInstance,
} from 'vue';
import { createNamespace } from '../utils';
import FanPopup from '../popup/popup.vue';
import FanButton from '../button/button.vue';
import FanText from '../text/text.vue';
import PickerColumn from './picker-column.vue';

export default defineComponent({
  name: createNamespace('Picker')[0],
  options: { virtualHost: true },
  emits: ['confirm', 'cancel', 'update:modelValue', 'update:show'],
  components: { FanPopup, FanButton, FanText, PickerColumn },
  props: {
    modelValue: {
      type: Array,
      default: () => [],
    },
    show: {
      type: Boolean,
      default: false,
    },
    title: String,
    cancelText: {
      type: String,
      default: '取消',
    },
    confirmText: {
      type: String,
      default: '确认',
    },
    data: Array,
    valueKey: String,
    textKey: {
      type: String,
      default: 'text',
    },
  },
  setup(props, { emit }) {
    const state = reactive({
      innerShow: props.show,
      list: [],
      selectValue:
        props.modelValue && props.modelValue.length
          ? [...props.modelValue]
          : [],
    });
    let isCascade = false;

    const instance = getCurrentInstance();
    const selectItem = (val) => {
      if (state.selectValue[val.level] !== val.select) {
        state.selectValue[val.level] = val.select;
        if (isCascade) {
          const d = state.list[val.level][val.index];
          state.list.splice(val.level + 1, state.list.length);
          if (d?.children && d?.children.length)
            formatCascade({
              data: d.children,
              key: props.textKey,
              arr: state.list,
            });
          state.list.forEach((_item, i) => {
            if (i > val.level) {
              state.selectValue[i] = state.list[i]?.findIndex(
                (item) => !item.disabled,
              );
              nextTick(() => {
                const column = instance.refs.column.sort(
                  (a, b) => a.index - b.index,
                );
                column[i].onTouchEnd(state.list[i]);
              });
            }
          });
        }
      }
    };

    // 点击确认按钮
    const onConfirm = () => emit('confirm', state.selectValue);
    // 点击取消
    const onCancel = () => {
      state.innerShow = false;
      emit('cancel');
    };

    const formatCascade = ({ data, key, arr }) => {
      const l = data.map((item) => ({
        text: item[key],
        disabled: !!item?.disabled,
        [props.valueKey]: item[props.valueKey],
        children: item.children,
      }));
      arr.push(l);
      if (l[0].children && l[0].children.length)
        formatCascade({ data: l[0].children, key, arr });
    };

    // 初始化
    const init = ({ data, key, arr }) => {
      if (data && data.length) {
        if (typeof data[0] === 'string') {
          if (!state.selectValue.length) state.selectValue = [0];
          arr.push(data.map((text) => ({ text, disabled: false })));
        } else if (Array.isArray(data[0])) {
          data.forEach((items, i) => {
            arr.push([]);
            items.forEach((item) => {
              arr[i].push({
                disabled: !!item?.disabled,
                text: item[key],
                [props.valueKey]: item[props.valueKey],
              });
            });
          });
          if (!state.selectValue.length) {
            state.selectValue = [];
            arr.forEach((items) => {
              const index = items.findIndex((item) => {
                if (!item.disabled) return true;
              });
              state.selectValue.push(
                props.valueKey ? items[index][props.valueKey] : index,
              );
            });
          }
        } else {
          isCascade = true;
          formatCascade({ data, key, arr });
          if (!state.selectValue.length) {
            state.selectValue = [];
            setTimeout(() => {
              state.list.forEach((items) => {
                const index = items.findIndex((item) => {
                  if (!item.disabled) return true;
                });
                state.selectValue.push(
                  props.valueKey ? items[index][props.valueKey] : index,
                );
              });
            }, 0);
          }
        }
      }
    };

    watch(
      () => props.modelValue,
      (val) => {
        if (val) state.selectValue = [...val];
      },
      { deep: true },
    );

    watch(
      () => state.selectValue,
      (val) => {
        let alike = false;
        if (val.find((item, i) => item !== props.modelValue[i])) alike = true;
        if (alike) emit('update:modelValue', val);
      },
      { deep: true },
    );

    watch(
      () => props.show,
      (val) => (state.innerShow = val),
    );
    watch(
      () => state.innerShow,
      (val) => emit('update:show', val),
    );

    watch(
      () => props.data,
      (data) => {
        if (data && data.length) {
          const arr = [];
          init({ data, key: props.textKey, arr });
          state.list = arr;
        }
      },
      { immediate: true, deep: true },
    );

    return { state, onConfirm, onCancel, selectItem };
  },
});
</script>

<template>
  <FanPopup v-model:show="state.innerShow" safe-bottom position="bottom">
    <div>
      <slot v-if="$slots.header" name="header" />
      <div
        v-else
        class="fan-picker__o fan-flex fan-align-center fan-justify-between"
      >
        <FanButton
          plain
          :border="false"
          text-size="14"
          text-color="#969799"
          @click="onCancel"
        >
          {{ cancelText }}
        </FanButton>
        <FanText bold text-size="18" color="#333">{{ title }}</FanText>
        <FanButton
          plain
          :border="false"
          text-size="14"
          text-color="var(--fan-primary-color)"
          @click="onConfirm"
          >{{ confirmText }}
        </FanButton>
      </div>

      <div class="fan-picker__c">
        <PickerColumn
          ref="column"
          v-for="(item, i) in state.list"
          :key="i"
          :items="item"
          :value="state.selectValue"
          :index="i"
          :value-key="valueKey"
          @selectItem="selectItem"
        />
        <div
          class="fan-picker__b"
          :style="{ height: '44PX', top: '132PX' }"
        ></div>
        <div class="fan-picker__mask"></div>
      </div>
    </div>
  </FanPopup>
</template>

<style lang="less">
.fan-picker {
  &__o {
    height: 44px;
  }

  &__c {
    position: relative;
    height: 264px;
    display: flex;
  }

  &__b {
    position: absolute;
    z-index: 2;
    pointer-events: none;
    transform: translateY(-50%);
    left: 16px;
    right: 16px;

    &::after {
      position: absolute;
      box-sizing: border-box;
      content: ' ';
      pointer-events: none;
      top: -50%;
      right: -50%;
      bottom: -50%;
      left: -50%;
      border: 0 solid #ebedf0;
      border-width: 1px 0;
      transform: scale(0.5);
    }
  }

  &__mask {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
    pointer-events: none;
    background-image: linear-gradient(
        180deg,
        rgba(255, 255, 255, 0.9),
        rgba(255, 255, 255, 0.4)
      ),
      linear-gradient(0deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.4));
    background-repeat: no-repeat;
    background-position: top, bottom;
    transform: translateZ(0);
    background-size: 100% 110px;
  }
}
</style>
